packages<-c("adehabitatHR","data.table","ggfortify","grid","move","moveVis","OpenStreetMap","pbapply","plotly","rgdal","sp","tidyverse","viridis")
sapply(packages, require, character.only=T)
 adehabitatHR    data.table     ggfortify          grid          move       moveVis OpenStreetMap       pbapply 
         TRUE          TRUE          TRUE          TRUE          TRUE          TRUE          TRUE          TRUE 
       plotly         rgdal            sp     tidyverse       viridis 
         TRUE          TRUE          TRUE          TRUE          TRUE 
data <- read.csv("bats.csv")

Plot 1

qaqc_plot <- ggplot() + geom_point(data=data, 
                                   aes(utm.easting,utm.northing,
                                       color=individual.local.identifier)) +
                        labs(x="Easting", y="Northing") +
                        guides(color=guide_legend("Bat Identifier"))

ggplotly(qaqc_plot)

Plot 2

lapply(split(data, data$individual.local.identifier), 
       function(x)write.csv(x, file = paste(x$individual.local.identifier[1],".csv"), row.names = FALSE))
cannot open file 'Bat 1 .csv': Permission deniedError in file(file, ifelse(append, "a", "w")) : 
  cannot open the connection
files <- c("Bat 5 .csv", "Bat 6 .csv")
utm_points <- cbind(data$utm.easting, data$utm.northing)
utm_locations <- SpatialPoints(utm_points, 
                 proj4string=CRS("+proj=utm +zone=14 +datum=WGS84"))
proj_lat.lon <- as.data.frame(spTransform(
                utm_locations, CRS("+proj=longlat +datum=WGS84")))
colnames(proj_lat.lon) <- c("x","y")
raster <- openmap(c(max(proj_lat.lon$y)+0.01, min(proj_lat.lon$x)-0.01), 
                  c(min(proj_lat.lon$y)-0.01, max(proj_lat.lon$x)+0.01), 
                  type = "bing")
raster_utm <- openproj(raster, 
              projection = "+proj=utm +zone=14 +ellps=WGS84 +units=m +no_defs")
autoplot(raster_utm, expand = TRUE) + theme_bw() +
  theme(legend.position="right") +
  theme(panel.border = element_rect(colour = "black", fill=NA, size=1)) +
  geom_point(data=data, aes(utm.easting,utm.northing,
             color=individual.local.identifier), size = 3, alpha = 0.8) +
  theme(axis.title = element_text(face="bold")) + labs(x="Easting",
        y="Northing") + guides(color=guide_legend("Bat Identifier"))

Plot 3 - Minimum Convex Polygon

mcp_raster <- function(filename){
  data <- read.csv(file = filename)
  x <- as.data.frame(data$utm.easting)
  y <- as.data.frame(data$utm.northing)
  xy <- c(x,y)
  data.proj <- SpatialPointsDataFrame(xy,data, proj4string = CRS("+proj=utm +zone=14 +ellps=WGS84 +units=m +no_defs"))
  xy <- SpatialPoints(data.proj@coords)
  mcp.out <- mcp(xy, percent=100, unout="ha")
  mcp.points <- cbind((data.frame(xy)),data$individual.local.identifier)
  colnames(mcp.points) <- c("x","y", "identifier")
  mcp.poly <- fortify(mcp.out, region = "id")
  units <- grid.text(paste(round(mcp.out@data$area,2),"ha"), x=0.85,  y=0.95,
                     gp=gpar(fontface=4, col="white", cex=0.9), draw = FALSE)
  mcp.plot <- autoplot(raster_utm, expand = TRUE) + theme_bw() + theme(legend.position="none") +
    theme(panel.border = element_rect(colour = "black", fill=NA, size=1)) +
    geom_polygon(data=mcp.poly, aes(x=mcp.poly$long, y=mcp.poly$lat), alpha=0.8) +
    geom_point(data=mcp.points, aes(x=x, y=y)) + 
    labs(x="Easting (m)", y="Northing (m)", title=mcp.points$identifier) +
    theme(legend.position="none", plot.title = element_text(face = "bold", hjust = 0.5)) + 
    annotation_custom(units)
  mcp.plot
}

pblapply(files, mcp_raster)

  |                                                                                  | 0 % ~calculating  
  |=========================================                                         | 50% ~00s          
  |==================================================================================| 100% elapsed=00s  
[[1]]

[[2]]

Plot 4 - Kernel-Density Estimation

kde_raster <- function(filename){
  data <- read.csv(file = filename)
  x <- as.data.frame(data$utm.easting)
  y <- as.data.frame(data$utm.northing)
  xy <- c(x,y)
  data.proj <- SpatialPointsDataFrame(xy,data, proj4string = CRS("+proj=utm +zone=14 +ellps=WGS84 +units=m +no_defs"))
  xy <- SpatialPoints(data.proj@coords)
  kde<-kernelUD(xy, h="href", kern="bivnorm", grid=100)
  ver <- getverticeshr(kde, 95)
  kde.points <- cbind((data.frame(data.proj@coords)),data$individual.local.identifier)
  colnames(kde.points) <- c("x","y","identifier")
  kde.poly <- fortify(ver, region = "id")
  units <- grid.text(paste(round(ver$area,2)," ha"), x=0.85,  y=0.95,
                     gp=gpar(fontface=4, col="white", cex=0.9), draw = FALSE)
  kde.plot <- autoplot(raster_utm, expand = TRUE) + theme_bw() + theme(legend.position="none") +
    theme(panel.border = element_rect(colour = "black", fill=NA, size=1)) +
    geom_polygon(data=kde.poly, aes(x=kde.poly$long, y=kde.poly$lat), alpha = 0.8) +
    geom_point(data=kde.points, aes(x=x, y=y)) +
    labs(x="Easting (m)", y="Northing (m)", title=kde.points$identifier) +
    theme(legend.position="none", plot.title = element_text(face = "bold", hjust = 0.5)) + 
    annotation_custom(units)
  kde.plot
}

pblapply(files, kde_raster)

  |                                                                                  | 0 % ~calculating  
  |=========================================                                         | 50% ~00s          
  |==================================================================================| 100% elapsed=00s  
[[1]]

[[2]]

Plot 5 - Brownian Bridge Movement

date <- as.POSIXct(strptime(as.character(bat5$timestamp),"%Y-%m-%d %H:%M:%S"))
bat5$date <- date
bat5.reloc <- cbind.data.frame(bat5$utm.easting, bat5$utm.northing,
                                as.vector(bat5$individual.local.identifier),
                                as.POSIXct(date))
colnames(bat5.reloc) <- c("x","y","id","date")
trajectory <- as.ltraj(bat5.reloc, date=date, id="bat5")
sig1 <- liker(trajectory, sig2 = 58, rangesig1 = c(0, 5), plotit = FALSE)
bats.traj <- kernelbb(trajectory, sig1 = .7908, sig2 = 58, grid = 100)
bb_ver <- getverticeshr(bats.traj, 95)
bb_poly <- fortify(bb_ver, region = "id", 
                   proj4string = CRS("+proj=utm +zone=14+
                                     ellps=WGS84 +units=m +no_defs"))
colnames(bb_poly) <- c("x","y","order","hole","piece","id","group")
bb_image <- crop(bats.traj, bb_ver, 
                 proj4string = CRS("+proj=utm +zone=14 +
                                   ellps=WGS84 +units=m +no_defs"))
bb_units <- grid.text(paste(round(bb_ver$area,2)," ha"), x=0.85,  y=0.95,
                   gp=gpar(fontface=4, col="white", cex=0.9), draw = FALSE)
bb.plot <- autoplot(raster_utm, expand = TRUE) + theme_bw() + theme(legend.position="none") +
  theme(panel.border = element_rect(colour = "black", fill=NA, size=1)) +
  geom_tile(data=bb_image, 
            aes(x=bb_image@coords[,1], y=bb_image@coords[,2],
            fill = bb_image@data$ud)) +
  geom_polygon(data=bb_poly, aes(x=x, y=y, group = group), color = "black", fill = NA) +
  scale_fill_viridis_c(option = "inferno") + annotation_custom(bb_units) +
  labs(x="Easting (m)", y="Northing (m)", title="bat5") +
  theme(legend.position="none", plot.title = element_text(face = "bold", hjust = 0.5))
bb.plot

Animated Gif of Movement

bats.move <- move(x=bat5$location.long, 
             y=bat5$location.lat, 
             time=as.POSIXct(bat5$timestamp, 
                             format="%Y-%m-%d %H:%M:%S"), 
             proj=CRS("+proj=longlat +ellps=WGS84 +datum=WGS84"),
             data=bat5, animal=bat5$individual.local.identifier, 
             sensor=bat5$sensor.type)
movement <- align_move(bats.move, res = "max", digit = 0, unit = "secs")
frames <- frames_spatial(movement, path_colours = "red",
                         map_service = "osm", 
                         alpha = 0.5) %>% 
  add_labels(x = "Longitude", y = "Latitude") %>%
  add_northarrow() %>% 
  add_scalebar() %>% 
  add_timestamps(movement, type = "label") %>% 
  add_progress()
Processing movement data...
Approximated animation duration: ≈ 1.48s at 25 fps for 37 frames

  |                                                                                  | 0 % ~calculating  
  |===                                                                               | 3 % ~02s          
  |=====                                                                             | 5 % ~02s          
  |=======                                                                           | 8 % ~02s          
  |=========                                                                         | 11% ~02s          
  |============                                                                      | 14% ~02s          
  |==============                                                                    | 16% ~02s          
  |================                                                                  | 19% ~02s          
  |==================                                                                | 22% ~02s          
  |====================                                                              | 24% ~02s          
  |=======================                                                           | 27% ~02s          
  |=========================                                                         | 30% ~02s          
  |===========================                                                       | 32% ~02s          
  |=============================                                                     | 35% ~02s          
  |================================                                                  | 38% ~02s          
  |==================================                                                | 41% ~02s          
  |====================================                                              | 43% ~02s          
  |======================================                                            | 46% ~02s          
  |========================================                                          | 49% ~01s          
  |===========================================                                       | 51% ~01s          
  |=============================================                                     | 54% ~01s          
  |===============================================                                   | 57% ~01s          
  |=================================================                                 | 59% ~01s          
  |===================================================                               | 62% ~01s          
  |======================================================                            | 65% ~01s          
  |========================================================                          | 68% ~01s          
  |==========================================================                        | 70% ~01s          
  |============================================================                      | 73% ~01s          
  |===============================================================                   | 76% ~01s          
  |=================================================================                 | 78% ~01s          
  |===================================================================               | 81% ~01s          
  |=====================================================================             | 84% ~00s          
  |=======================================================================           | 86% ~00s          
  |==========================================================================        | 89% ~00s          
  |============================================================================      | 92% ~00s          
  |==============================================================================    | 95% ~00s          
  |================================================================================  | 97% ~00s          
  |==================================================================================| 100% elapsed=03s  
Retrieving and compositing basemap imagery...

  |                                                                                  | 0 % ~calculating  
  |======                                                                            | 7 % ~02s          
  |===========                                                                       | 13% ~01s          
  |=================                                                                 | 20% ~01s          
  |======================                                                            | 27% ~01s          
  |============================                                                      | 33% ~01s          
  |=================================                                                 | 40% ~01s          
  |=======================================                                           | 47% ~01s          
  |============================================                                      | 53% ~01s          
  |==================================================                                | 60% ~00s          
  |=======================================================                           | 67% ~00s          
  |=============================================================                     | 73% ~00s          
  |==================================================================                | 80% ~00s          
  |========================================================================          | 87% ~00s          
  |=============================================================================     | 93% ~00s          
  |==================================================================================| 100% elapsed=01s  
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Infno non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf
Assigning raster maps to frames...

  |                                                                                  | 0 % ~calculating  
  |==================================================================================| 100% elapsed=00s  
Creating frames...
animate_frames(frames, fps = 5, overwrite = TRUE,
               out_file = "./moveVis-5fps.gif")
Rendering animation...
Approximated animation duration: ≈ 7.4s at 5 fps for 37 frames

  |                                                                                  | 0 % ~calculating  
  |===                                                                               | 3 % ~02m 54s      
  |=====                                                                             | 5 % ~02m 54s      
  |=======                                                                           | 8 % ~02m 45s      
  |=========                                                                         | 11% ~02m 42s      
  |============                                                                      | 14% ~02m 35s      
  |==============                                                                    | 16% ~02m 29s      
  |================                                                                  | 19% ~02m 25s      
  |==================                                                                | 22% ~02m 20s      
  |====================                                                              | 24% ~02m 16s      
  |=======================                                                           | 27% ~02m 11s      
  |=========================                                                         | 30% ~02m 06s      
  |===========================                                                       | 32% ~02m 02s      
  |=============================                                                     | 35% ~01m 56s      
  |================================                                                  | 38% ~01m 51s      
  |==================================                                                | 41% ~01m 47s      
  |====================================                                              | 43% ~01m 41s      
  |======================================                                            | 46% ~01m 36s      
  |========================================                                          | 49% ~01m 32s      
  |===========================================                                       | 51% ~01m 27s      
  |=============================================                                     | 54% ~01m 22s      
  |===============================================                                   | 57% ~01m 17s      
  |=================================================                                 | 59% ~01m 13s      
  |===================================================                               | 62% ~01m 08s      
  |======================================================                            | 65% ~01m 03s      
  |========================================================                          | 68% ~59s          
  |==========================================================                        | 70% ~54s          
  |============================================================                      | 73% ~49s          
  |===============================================================                   | 76% ~44s          
  |=================================================================                 | 78% ~39s          
  |===================================================================               | 81% ~34s          
  |=====================================================================             | 84% ~30s          
  |=======================================================================           | 86% ~25s          
  |==========================================================================        | 89% ~20s          
  |============================================================================      | 92% ~15s          
  |==============================================================================    | 95% ~10s          
  |================================================================================  | 97% ~05s          
  |==================================================================================| 100% elapsed=03m 03s

Frame 1 (2%)
Frame 2 (5%)
Frame 3 (8%)
Frame 4 (10%)
Frame 5 (13%)
Frame 6 (16%)
Frame 7 (18%)
Frame 8 (21%)
Frame 9 (24%)
Frame 10 (27%)
Frame 11 (29%)
Frame 12 (32%)
Frame 13 (35%)
Frame 14 (37%)
Frame 15 (40%)
Frame 16 (43%)
Frame 17 (45%)
Frame 18 (48%)
Frame 19 (51%)
Frame 20 (54%)
Frame 21 (56%)
Frame 22 (59%)
Frame 23 (62%)
Frame 24 (64%)
Frame 25 (67%)
Frame 26 (70%)
Frame 27 (72%)
Frame 28 (75%)
Frame 29 (78%)
Frame 30 (81%)
Frame 31 (83%)
Frame 32 (86%)
Frame 33 (89%)
Frame 34 (91%)
Frame 35 (94%)
Frame 36 (97%)
Frame 37 (100%)
Finalizing encoding... done!
LS0tDQp0aXRsZTogIkxhdXJlbidzIEhvbWUgUmFuZ2UgQW5hbHlzaXMiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7ciBTZXR1cCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnBhY2thZ2VzPC1jKCJhZGVoYWJpdGF0SFIiLCJkYXRhLnRhYmxlIiwiZ2dmb3J0aWZ5IiwiZ3JpZCIsIm1vdmUiLCJtb3ZlVmlzIiwiT3BlblN0cmVldE1hcCIsInBiYXBwbHkiLCJwbG90bHkiLCJyZ2RhbCIsInNwIiwidGlkeXZlcnNlIiwidmlyaWRpcyIpDQpzYXBwbHkocGFja2FnZXMsIHJlcXVpcmUsIGNoYXJhY3Rlci5vbmx5PVQpDQpgYGANCg0KYGBge3IgSW1wb3J0IERhdGF9DQpkYXRhIDwtIHJlYWQuY3N2KCJiYXRzLmNzdiIpDQpgYGANCg0KDQojIFBsb3QgMSAgDQpgYGB7ciBJbml0aWFsIFBsb3R9DQpxYXFjX3Bsb3QgPC0gZ2dwbG90KCkgKyBnZW9tX3BvaW50KGRhdGE9ZGF0YSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh1dG0uZWFzdGluZyx1dG0ubm9ydGhpbmcsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcj1pbmRpdmlkdWFsLmxvY2FsLmlkZW50aWZpZXIpKSArDQogICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHg9IkVhc3RpbmciLCB5PSJOb3J0aGluZyIpICsNCiAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvcj1ndWlkZV9sZWdlbmQoIkJhdCBJZGVudGlmaWVyIikpDQoNCmdncGxvdGx5KHFhcWNfcGxvdCkNCmBgYA0KDQoNCiMgUGxvdCAyICAgDQpgYGB7ciBTcGxpdCBEYXRhc2V0LCBtZXNzYWdlPUZBTFNFfQ0KbGFwcGx5KHNwbGl0KGRhdGEsIGRhdGEkaW5kaXZpZHVhbC5sb2NhbC5pZGVudGlmaWVyKSwgDQogICAgICAgZnVuY3Rpb24oeCl3cml0ZS5jc3YoeCwgZmlsZSA9IHBhc3RlKHgkaW5kaXZpZHVhbC5sb2NhbC5pZGVudGlmaWVyWzFdLCIuY3N2IiksIHJvdy5uYW1lcyA9IEZBTFNFKSkNCmBgYA0KDQpgYGB7ciBGaWxlIExpc3R9DQpmaWxlcyA8LSBjKCJCYXQgNSAuY3N2IiwgIkJhdCA2IC5jc3YiKQ0KYGBgDQoNCmBgYHtyIFNwYXRpYWwgRGV0YWlsLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KdXRtX3BvaW50cyA8LSBjYmluZChkYXRhJHV0bS5lYXN0aW5nLCBkYXRhJHV0bS5ub3J0aGluZykNCnV0bV9sb2NhdGlvbnMgPC0gU3BhdGlhbFBvaW50cyh1dG1fcG9pbnRzLCANCiAgICAgICAgICAgICAgICAgcHJvajRzdHJpbmc9Q1JTKCIrcHJvaj11dG0gK3pvbmU9MTQgK2RhdHVtPVdHUzg0IikpDQpwcm9qX2xhdC5sb24gPC0gYXMuZGF0YS5mcmFtZShzcFRyYW5zZm9ybSgNCiAgICAgICAgICAgICAgICB1dG1fbG9jYXRpb25zLCBDUlMoIitwcm9qPWxvbmdsYXQgK2RhdHVtPVdHUzg0IikpKQ0KY29sbmFtZXMocHJval9sYXQubG9uKSA8LSBjKCJ4IiwieSIpDQpyYXN0ZXIgPC0gb3Blbm1hcChjKG1heChwcm9qX2xhdC5sb24keSkrMC4wMSwgbWluKHByb2pfbGF0LmxvbiR4KS0wLjAxKSwgDQogICAgICAgICAgICAgICAgICBjKG1pbihwcm9qX2xhdC5sb24keSktMC4wMSwgbWF4KHByb2pfbGF0LmxvbiR4KSswLjAxKSwgDQogICAgICAgICAgICAgICAgICB0eXBlID0gImJpbmciKQ0KcmFzdGVyX3V0bSA8LSBvcGVucHJvaihyYXN0ZXIsIA0KICAgICAgICAgICAgICBwcm9qZWN0aW9uID0gIitwcm9qPXV0bSArem9uZT0xNCArZWxscHM9V0dTODQgK3VuaXRzPW0gK25vX2RlZnMiKQ0KYGBgDQoNCmBgYHtyIERpc3BsYXkgUmFzdGVyIHdpdGggVVRNIE92ZXJsYXl9DQphdXRvcGxvdChyYXN0ZXJfdXRtLCBleHBhbmQgPSBUUlVFKSArIHRoZW1lX2J3KCkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb249InJpZ2h0IikgKw0KICB0aGVtZShwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImJsYWNrIiwgZmlsbD1OQSwgc2l6ZT0xKSkgKw0KICBnZW9tX3BvaW50KGRhdGE9ZGF0YSwgYWVzKHV0bS5lYXN0aW5nLHV0bS5ub3J0aGluZywNCiAgICAgICAgICAgICBjb2xvcj1pbmRpdmlkdWFsLmxvY2FsLmlkZW50aWZpZXIpLCBzaXplID0gMywgYWxwaGEgPSAwLjgpICsNCiAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlPSJib2xkIikpICsgbGFicyh4PSJFYXN0aW5nIiwNCiAgICAgICAgeT0iTm9ydGhpbmciKSArIGd1aWRlcyhjb2xvcj1ndWlkZV9sZWdlbmQoIkJhdCBJZGVudGlmaWVyIikpDQpgYGANCg0KDQojIFBsb3QgMyAtIE1pbmltdW0gQ29udmV4IFBvbHlnb24gIA0KYGBge3IgTWluaW11bSBDb252ZXggUG9seWdvbn0NCm1jcF9yYXN0ZXIgPC0gZnVuY3Rpb24oZmlsZW5hbWUpew0KICBkYXRhIDwtIHJlYWQuY3N2KGZpbGUgPSBmaWxlbmFtZSkNCiAgeCA8LSBhcy5kYXRhLmZyYW1lKGRhdGEkdXRtLmVhc3RpbmcpDQogIHkgPC0gYXMuZGF0YS5mcmFtZShkYXRhJHV0bS5ub3J0aGluZykNCiAgeHkgPC0gYyh4LHkpDQogIGRhdGEucHJvaiA8LSBTcGF0aWFsUG9pbnRzRGF0YUZyYW1lKHh5LGRhdGEsIHByb2o0c3RyaW5nID0gQ1JTKCIrcHJvaj11dG0gK3pvbmU9MTQgK2VsbHBzPVdHUzg0ICt1bml0cz1tICtub19kZWZzIikpDQogIHh5IDwtIFNwYXRpYWxQb2ludHMoZGF0YS5wcm9qQGNvb3JkcykNCiAgbWNwLm91dCA8LSBtY3AoeHksIHBlcmNlbnQ9MTAwLCB1bm91dD0iaGEiKQ0KICBtY3AucG9pbnRzIDwtIGNiaW5kKChkYXRhLmZyYW1lKHh5KSksZGF0YSRpbmRpdmlkdWFsLmxvY2FsLmlkZW50aWZpZXIpDQogIGNvbG5hbWVzKG1jcC5wb2ludHMpIDwtIGMoIngiLCJ5IiwgImlkZW50aWZpZXIiKQ0KICBtY3AucG9seSA8LSBmb3J0aWZ5KG1jcC5vdXQsIHJlZ2lvbiA9ICJpZCIpDQogIHVuaXRzIDwtIGdyaWQudGV4dChwYXN0ZShyb3VuZChtY3Aub3V0QGRhdGEkYXJlYSwyKSwiaGEiKSwgeD0wLjg1LCAgeT0wLjk1LA0KICAgICAgICAgICAgICAgICAgICAgZ3A9Z3Bhcihmb250ZmFjZT00LCBjb2w9IndoaXRlIiwgY2V4PTAuOSksIGRyYXcgPSBGQUxTRSkNCiAgbWNwLnBsb3QgPC0gYXV0b3Bsb3QocmFzdGVyX3V0bSwgZXhwYW5kID0gVFJVRSkgKyB0aGVtZV9idygpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKw0KICAgIHRoZW1lKHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiYmxhY2siLCBmaWxsPU5BLCBzaXplPTEpKSArDQogICAgZ2VvbV9wb2x5Z29uKGRhdGE9bWNwLnBvbHksIGFlcyh4PW1jcC5wb2x5JGxvbmcsIHk9bWNwLnBvbHkkbGF0KSwgYWxwaGE9MC44KSArDQogICAgZ2VvbV9wb2ludChkYXRhPW1jcC5wb2ludHMsIGFlcyh4PXgsIHk9eSkpICsgDQogICAgbGFicyh4PSJFYXN0aW5nIChtKSIsIHk9Ik5vcnRoaW5nIChtKSIsIHRpdGxlPW1jcC5wb2ludHMkaWRlbnRpZmllcikgKw0KICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIsIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgaGp1c3QgPSAwLjUpKSArIA0KICAgIGFubm90YXRpb25fY3VzdG9tKHVuaXRzKQ0KICBtY3AucGxvdA0KfQ0KDQpwYmxhcHBseShmaWxlcywgbWNwX3Jhc3RlcikNCmBgYA0KDQoNCiMgUGxvdCA0IC0gS2VybmVsLURlbnNpdHkgRXN0aW1hdGlvbiAgDQpgYGB7ciBLZXJuZWwtRGVuc2l0eSBFc3RpbWF0aW9uLCB3YXJuaW5nPUZBTFNFfQ0Ka2RlX3Jhc3RlciA8LSBmdW5jdGlvbihmaWxlbmFtZSl7DQogIGRhdGEgPC0gcmVhZC5jc3YoZmlsZSA9IGZpbGVuYW1lKQ0KICB4IDwtIGFzLmRhdGEuZnJhbWUoZGF0YSR1dG0uZWFzdGluZykNCiAgeSA8LSBhcy5kYXRhLmZyYW1lKGRhdGEkdXRtLm5vcnRoaW5nKQ0KICB4eSA8LSBjKHgseSkNCiAgZGF0YS5wcm9qIDwtIFNwYXRpYWxQb2ludHNEYXRhRnJhbWUoeHksZGF0YSwgcHJvajRzdHJpbmcgPSBDUlMoIitwcm9qPXV0bSArem9uZT0xNCArZWxscHM9V0dTODQgK3VuaXRzPW0gK25vX2RlZnMiKSkNCiAgeHkgPC0gU3BhdGlhbFBvaW50cyhkYXRhLnByb2pAY29vcmRzKQ0KICBrZGU8LWtlcm5lbFVEKHh5LCBoPSJocmVmIiwga2Vybj0iYml2bm9ybSIsIGdyaWQ9MTAwKQ0KICB2ZXIgPC0gZ2V0dmVydGljZXNocihrZGUsIDk1KQ0KICBrZGUucG9pbnRzIDwtIGNiaW5kKChkYXRhLmZyYW1lKGRhdGEucHJvakBjb29yZHMpKSxkYXRhJGluZGl2aWR1YWwubG9jYWwuaWRlbnRpZmllcikNCiAgY29sbmFtZXMoa2RlLnBvaW50cykgPC0gYygieCIsInkiLCJpZGVudGlmaWVyIikNCiAga2RlLnBvbHkgPC0gZm9ydGlmeSh2ZXIsIHJlZ2lvbiA9ICJpZCIpDQogIHVuaXRzIDwtIGdyaWQudGV4dChwYXN0ZShyb3VuZCh2ZXIkYXJlYSwyKSwiIGhhIiksIHg9MC44NSwgIHk9MC45NSwNCiAgICAgICAgICAgICAgICAgICAgIGdwPWdwYXIoZm9udGZhY2U9NCwgY29sPSJ3aGl0ZSIsIGNleD0wLjkpLCBkcmF3ID0gRkFMU0UpDQogIGtkZS5wbG90IDwtIGF1dG9wbG90KHJhc3Rlcl91dG0sIGV4cGFuZCA9IFRSVUUpICsgdGhlbWVfYncoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsNCiAgICB0aGVtZShwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImJsYWNrIiwgZmlsbD1OQSwgc2l6ZT0xKSkgKw0KICAgIGdlb21fcG9seWdvbihkYXRhPWtkZS5wb2x5LCBhZXMoeD1rZGUucG9seSRsb25nLCB5PWtkZS5wb2x5JGxhdCksIGFscGhhID0gMC44KSArDQogICAgZ2VvbV9wb2ludChkYXRhPWtkZS5wb2ludHMsIGFlcyh4PXgsIHk9eSkpICsNCiAgICBsYWJzKHg9IkVhc3RpbmcgKG0pIiwgeT0iTm9ydGhpbmcgKG0pIiwgdGl0bGU9a2RlLnBvaW50cyRpZGVudGlmaWVyKSArDQogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIiwgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBoanVzdCA9IDAuNSkpICsgDQogICAgYW5ub3RhdGlvbl9jdXN0b20odW5pdHMpDQogIGtkZS5wbG90DQp9DQoNCnBibGFwcGx5KGZpbGVzLCBrZGVfcmFzdGVyKQ0KYGBgDQoNCg0KIyBQbG90IDUgLSBCcm93bmlhbiBCcmlkZ2UgTW92ZW1lbnQNCmBgYHtyIEJyb3duaWFuIEJyaWRnZSBNb3ZlbWVudH0NCmJhdDUgPC0gcmVhZC5jc3YoIkJhdCA1IC5jc3YiKQ0KZGF0ZSA8LSBhcy5QT1NJWGN0KHN0cnB0aW1lKGFzLmNoYXJhY3RlcihiYXQ1JHRpbWVzdGFtcCksIiVZLSVtLSVkICVIOiVNOiVTIikpDQpiYXQ1JGRhdGUgPC0gZGF0ZQ0KYmF0NS5yZWxvYyA8LSBjYmluZC5kYXRhLmZyYW1lKGJhdDUkdXRtLmVhc3RpbmcsIGJhdDUkdXRtLm5vcnRoaW5nLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcy52ZWN0b3IoYmF0NSRpbmRpdmlkdWFsLmxvY2FsLmlkZW50aWZpZXIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcy5QT1NJWGN0KGRhdGUpKQ0KY29sbmFtZXMoYmF0NS5yZWxvYykgPC0gYygieCIsInkiLCJpZCIsImRhdGUiKQ0KdHJhamVjdG9yeSA8LSBhcy5sdHJhaihiYXQ1LnJlbG9jLCBkYXRlPWRhdGUsIGlkPSJiYXQ1IikNCnNpZzEgPC0gbGlrZXIodHJhamVjdG9yeSwgc2lnMiA9IDU4LCByYW5nZXNpZzEgPSBjKDAsIDUpLCBwbG90aXQgPSBGQUxTRSkNCmJhdHMudHJhaiA8LSBrZXJuZWxiYih0cmFqZWN0b3J5LCBzaWcxID0gLjc5MDgsIHNpZzIgPSA1OCwgZ3JpZCA9IDEwMCkNCmJiX3ZlciA8LSBnZXR2ZXJ0aWNlc2hyKGJhdHMudHJhaiwgOTUpDQpiYl9wb2x5IDwtIGZvcnRpZnkoYmJfdmVyLCByZWdpb24gPSAiaWQiLCANCiAgICAgICAgICAgICAgICAgICBwcm9qNHN0cmluZyA9IENSUygiK3Byb2o9dXRtICt6b25lPTE0Kw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsbHBzPVdHUzg0ICt1bml0cz1tICtub19kZWZzIikpDQpjb2xuYW1lcyhiYl9wb2x5KSA8LSBjKCJ4IiwieSIsIm9yZGVyIiwiaG9sZSIsInBpZWNlIiwiaWQiLCJncm91cCIpDQpiYl9pbWFnZSA8LSBjcm9wKGJhdHMudHJhaiwgYmJfdmVyLCANCiAgICAgICAgICAgICAgICAgcHJvajRzdHJpbmcgPSBDUlMoIitwcm9qPXV0bSArem9uZT0xNCArDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsbHBzPVdHUzg0ICt1bml0cz1tICtub19kZWZzIikpDQpiYl91bml0cyA8LSBncmlkLnRleHQocGFzdGUocm91bmQoYmJfdmVyJGFyZWEsMiksIiBoYSIpLCB4PTAuODUsICB5PTAuOTUsDQogICAgICAgICAgICAgICAgICAgZ3A9Z3Bhcihmb250ZmFjZT00LCBjb2w9IndoaXRlIiwgY2V4PTAuOSksIGRyYXcgPSBGQUxTRSkNCmJiLnBsb3QgPC0gYXV0b3Bsb3QocmFzdGVyX3V0bSwgZXhwYW5kID0gVFJVRSkgKyB0aGVtZV9idygpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKw0KICB0aGVtZShwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImJsYWNrIiwgZmlsbD1OQSwgc2l6ZT0xKSkgKw0KICBnZW9tX3RpbGUoZGF0YT1iYl9pbWFnZSwgDQogICAgICAgICAgICBhZXMoeD1iYl9pbWFnZUBjb29yZHNbLDFdLCB5PWJiX2ltYWdlQGNvb3Jkc1ssMl0sDQogICAgICAgICAgICBmaWxsID0gYmJfaW1hZ2VAZGF0YSR1ZCkpICsNCiAgZ2VvbV9wb2x5Z29uKGRhdGE9YmJfcG9seSwgYWVzKHg9eCwgeT15LCBncm91cCA9IGdyb3VwKSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gTkEpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzX2Mob3B0aW9uID0gImluZmVybm8iKSArIGFubm90YXRpb25fY3VzdG9tKGJiX3VuaXRzKSArDQogIGxhYnMoeD0iRWFzdGluZyAobSkiLCB5PSJOb3J0aGluZyAobSkiLCB0aXRsZT0iYmF0NSIpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIiwgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBoanVzdCA9IDAuNSkpDQpiYi5wbG90DQpgYGANCg0KDQojIEFuaW1hdGVkIEdpZiBvZiBNb3ZlbWVudA0KYGBge3IgR2lmIDF9DQpiYXRzLm1vdmUgPC0gbW92ZSh4PWJhdDUkbG9jYXRpb24ubG9uZywgDQogICAgICAgICAgICAgeT1iYXQ1JGxvY2F0aW9uLmxhdCwgDQogICAgICAgICAgICAgdGltZT1hcy5QT1NJWGN0KGJhdDUkdGltZXN0YW1wLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybWF0PSIlWS0lbS0lZCAlSDolTTolUyIpLCANCiAgICAgICAgICAgICBwcm9qPUNSUygiK3Byb2o9bG9uZ2xhdCArZWxscHM9V0dTODQgK2RhdHVtPVdHUzg0IiksDQogICAgICAgICAgICAgZGF0YT1iYXQ1LCBhbmltYWw9YmF0NSRpbmRpdmlkdWFsLmxvY2FsLmlkZW50aWZpZXIsIA0KICAgICAgICAgICAgIHNlbnNvcj1iYXQ1JHNlbnNvci50eXBlKQ0KYGBgDQoNCmBgYHtyIEdpZiAyfQ0KbW92ZW1lbnQgPC0gYWxpZ25fbW92ZShiYXRzLm1vdmUsIHJlcyA9ICJtYXgiLCBkaWdpdCA9IDAsIHVuaXQgPSAic2VjcyIpDQoNCmBgYA0KDQpgYGB7ciBHaWYgMywgd2FybmluZz1GQUxTRX0NCmZyYW1lcyA8LSBmcmFtZXNfc3BhdGlhbChtb3ZlbWVudCwgcGF0aF9jb2xvdXJzID0gInJlZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgbWFwX3NlcnZpY2UgPSAib3NtIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjUpICU+JSANCiAgYWRkX2xhYmVscyh4ID0gIkxvbmdpdHVkZSIsIHkgPSAiTGF0aXR1ZGUiKSAlPiUNCiAgYWRkX25vcnRoYXJyb3coKSAlPiUgDQogIGFkZF9zY2FsZWJhcigpICU+JSANCiAgYWRkX3RpbWVzdGFtcHMobW92ZW1lbnQsIHR5cGUgPSAibGFiZWwiKSAlPiUgDQogIGFkZF9wcm9ncmVzcygpDQoNCmBgYA0KDQpgYGB7ciBHaWYgNCAtIEFuaW1hdGV9DQphbmltYXRlX2ZyYW1lcyhmcmFtZXMsIGZwcyA9IDUsIG92ZXJ3cml0ZSA9IFRSVUUsDQogICAgICAgICAgICAgICBvdXRfZmlsZSA9ICIuL21vdmVWaXMtNWZwcy5naWYiKQ0KYGBgDQoNCg==